import {
  Component,
  createRef,
  type ChangeEvent,
  type KeyboardEvent,
} from "react";

import { nanoid } from "nanoid";
import "./global.scss";

// console.log(nanoid()); // ''
// console.log(nanoid()); // ''

interface ITodo {
  id: string;
  text: string;
  isDone: boolean;
}

interface IProps {}

interface IState {
  todos: ITodo[];
  curTodo: ITodo | null;
}

export default class App extends Component<IProps, IState> {
  inputRef = createRef<HTMLInputElement>();

  state: Readonly<IState> = {
    todos: [
      { id: "1", text: "吃饭", isDone: true },
      { id: "2", text: "睡觉", isDone: false },
    ],
    curTodo: null, // 表示当前正在操作的 todo
  };

  onEdit = (data: ITodo) => {
    console.log("data", data);
    this.setState({
      curTodo: data,
    });
  };

  handleAdd = () => {
    // 1. 获取输入框的 value 值
    const value = this.inputRef.current?.value;
    // 2. 非空校验
    if (!value) return;
    // 3. 组装成一个对象数据
    const todo: ITodo = {
      // id: this.state.todos.length + 1, // 小bug, uuid nanoid
      id: nanoid(),
      text: value,
      isDone: false,
    };
    // 4. 将数据追加到 todos 中
    this.setState((prevState) => ({
      todos: [...prevState.todos, todo],
    }));
    // 5. 清空输入框
    (this.inputRef.current as HTMLInputElement).value = "";
    console.log("value", value);
  };

  // 删除
  handleDel = (id: string) => {
    this.setState((state) => ({
      todos: state.todos.filter((item) => item.id !== id),
    }));
  };

  // 勾选与取消勾选
  handleChange = (id: string, event: ChangeEvent<HTMLInputElement>) => {
    // 1. 获取要修改的勾选状态
    const checked = event.target.checked;
    // 2. 修改
    this.setState((state) => ({
      todos: state.todos.map((item) => {
        // 判断 id
        if (item.id === id) {
          // 当前这个是要修改的项
          // return {
          //   id: item.id,
          //   text: item.text,
          //   isDone: checked,
          // };
          return {
            ...item,
            isDone: checked,
          };
        } else {
          // 直接返回该项
          return item;
        }
      }),
    }));
  };

  handleChangeEdit = (event: ChangeEvent<HTMLInputElement>) => {
    const value = event.currentTarget.value;

    this.setState((state) => ({
      curTodo: { ...(state.curTodo as ITodo), text: value },
    }));
  };

  handleEnter = (event: KeyboardEvent<HTMLInputElement>) => {
    // 根据 keycode 来判断是否为 回车键
    if (event.key !== "Enter") return;

    // 1. 获取到输入框的值
    // const value = event.currentTarget.value;
    // 2. 修改
    this.setState((state) => ({
      curTodo: null, // 编辑状态就去掉了
      todos: state.todos.map((item) => {
        if (item.id === state.curTodo?.id) {
          return {
            ...item,
            text: state.curTodo.text,
          };
        } else {
          return item;
        }
      }),
    }));
  };

  render() {
    const { todos, curTodo } = this.state;

    return (
      <div>
        <div>
          <input ref={this.inputRef} placeholder="请输入" />
          <button onClick={this.handleAdd}>Add</button>
        </div>

        <ul>
          {todos.map((item) => {
            const isEdit: boolean = item.id === curTodo?.id;

            return (
              <li key={item.id}>
                {!isEdit ? (
                  <div>
                    <input
                      type="checkbox"
                      checked={item.isDone}
                      onChange={(event) => this.handleChange(item.id, event)}
                    />
                    <span>{item.text}</span>
                  </div>
                ) : (
                  <div>
                    <input
                      type="text"
                      value={curTodo?.text}
                      onChange={this.handleChangeEdit}
                      onKeyUp={this.handleEnter}
                    />
                  </div>
                )}

                <div>
                  <button onClick={() => this.onEdit(item)}>Edit</button>
                  <button onClick={() => this.handleDel(item.id)}>Del</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    );
  }
}
